const { success, failure } = require("../../utils/responses");
const attachmentService = require("../../services/upload/attachmentService");
const fs = require("fs");
// 引入zlib模块，用于文件压缩处理
const zlib = require("zlib");

exports.upload = async (req, res) => {
  try {
    const file = req.file;
    const filePath = file.destination + file.originalname;
    await attachmentService.saveAttachment({
      businessId: req.body.businessId,
      fileSize: req.file.size,
      fileType: req.file.mimetype,
      filename: decodeURI(file.originalname),
      filePath,
      remark: req.body.remark,
      tableName: req.body.tableName,
    });
    success(res, "上传成功", file);
  } catch (e) {
    failure(res, e.message);
    throw e;
  }
};

/**
 * 删除附件及文件
 * @param req
 * @param res
 * @returns {Promise<void>}
 */
exports.deleteFileAttachmentById = async (req, res) => {
  try {
    await attachmentService.deleteFileAttachmentById(req.body.id);
    success(res, "删除成功");
  } catch (e) {
    failure(res, e.message);
    throw e;
  }
};

/**
 * 获取业务id列表
 * @param req
 * @param res
 * @returns {Promise<*>}
 */
exports.getBusinessIdList = async (req, res) => {
  try {
    const data = await attachmentService.getBusinessIdList(
      req.query.businessId,
    );
    success(res, "上传成功", data);
  } catch (e) {
    return failure(res, e.message);
  }
};
/**
 * 发送文件并根据需要进行压缩的异步函数。
 * 该函数首先尝试从Redis缓存中获取文件元数据，
 * 若缓存不存在，则查询数据库并设置Redis缓存，同时考虑了文件的压缩传输。
 *
 * @param req - Express请求对象，包含查询参数id用于获取文件信息。
 * @param res - Express响应对象，用于发送文件或错误信息。
 */
exports.getTeamOfVideo = async (req, res) => {
  try {
    // 尝试从Redis中根据文件ID获取文件元数据
    let cacheData = await req.redis.get(req.query.id);

    if (cacheData) {
      // 如果Redis中有缓存，则解析缓存数据
      cacheData = JSON.parse(cacheData);
    } else {
      // 如果Redis中没有缓存，则查询数据库获取文件信息
      const { filePath, fileType, fileSize } =
        await attachmentService.getAttachmentById(req.query.id);

      // 设置Redis缓存过期时间为1小时，可根据需要调整
      const expireTime = 60 * 60; // 1小时的秒数

      // 将文件信息存储到Redis，并设置过期时间
      await req.redis.set(
        req.query.id,
        JSON.stringify({ filePath, fileType, fileSize }),
      );
      await req.redis.expire(req.query.id, expireTime);

      cacheData = { filePath, fileType, fileSize };
    }

    // 检查文件是否存在
    if (!fs.existsSync(cacheData.filePath)) {
      return res.status(404).send("文件未找到");
    }

    // 设置响应头，包括文件大小和类型
    res.set("Content-Length", cacheData.fileSize);
    res.set("Content-Type", cacheData.fileType);

    // 准备文件读取流
    const readStream = fs.createReadStream(cacheData.filePath);
    // 使用zlib创建gzip压缩流，根据客户端支持情况决定是否压缩发送
    const gzip = zlib.createGzip();

    // 判断客户端是否支持gzip压缩
    if (req.headers["accept-encoding"].includes("gzip")) {
      // 设置Content-Encoding为gzip，表示响应内容经过gzip压缩
      res.set("Content-Encoding", "gzip");
      // 将文件读取流通过gzip压缩后发送给客户端
      readStream.pipe(gzip).pipe(res);
    } else {
      // 客户端不支持gzip，则直接发送原始文件
      readStream.pipe(res);
    }
  } catch (e) {
    // 发生异常时调用错误处理函数
    failure(res, e);
  }
};

/**
 * 过滤上传参数
 * @param req
 * @returns {{filename, fileSize: *, filePath: ({type: *}|*), businessId: ({type: *}|*), remark, fileType: ({type: *}|*), tableName: *}}
 */
exports.filterBody = (req) => {
  return {
    businessId: req.body.businessId,
    filePath: req.body.filePath,
    fileSize: req.body.fileSize,
    fileType: req.body.fileType,
    tableName: req.body.tableName,
    filename: req.body.filename,
    remark: req.body.remark,
  };
};
